home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / pktdrvr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-24  |  15.0 KB  |  584 lines

  1. /* Driver for FTP Software's packet driver interface. (PC specific code)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <dos.h>
  6. #include "global.h"
  7. #include "config.h"
  8. #ifdef PACKET
  9. #include "proc.h"
  10. #include "mbuf.h"
  11. #include "netuser.h"
  12. #include "enet.h"
  13. #include "arcnet.h"
  14. #include "ax25.h"
  15. #include "slip.h"
  16. #include "kiss.h"
  17. #include "iface.h"
  18. #include "ec.h"
  19. #include "arp.h"
  20. #include "trace.h"
  21. #include "pktdrvr.h"
  22. #include "config.h"
  23.  
  24. static long near access_type __ARGS((int intno,int if_class,int if_type,
  25.     int if_number, char *type,unsigned typelen,
  26.     INTERRUPT (*receiver) __ARGS((void)) ));
  27. static int near driver_info __ARGS((int intno,int handle,int *version,
  28.     int *class,int *type,int *number,int *basic));
  29. static int near release_type __ARGS((int intno,int handle));
  30. static int near get_address __ARGS((int intno,int handle,char *buf,int len));
  31. static int pk_raw __ARGS((struct iface *iface,struct mbuf *bp));
  32. static int pk_stop __ARGS((struct iface *iface,int tmp));
  33. static int near send_pkt __ARGS((int intno,char *buffer,unsigned length));
  34. /* zba 940826: */
  35. static int pk_ioctl __ARGS((struct iface *iface, int argc, char *argv[]));
  36.  
  37. INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  38. static struct pktdrvr Pktdrvr[PK_MAX];
  39. static int Derr;
  40. static char Pkt_sig[] = "PKT DRVR";    /* Packet driver signature */
  41.  
  42. #ifdef    ARCNET
  43. static char arcip[] = {ARC_IP};
  44. static char arcarp[] = {ARC_ARP};
  45. #endif
  46.  
  47. #ifdef ETHER
  48. static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  49. static char revarptype[] = {REVARP_TYPE >> 8, REVARP_TYPE};
  50. #endif
  51.  
  52. static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  53.  
  54. #ifdef SLFP
  55. /*
  56.  * Send routine for packet driver
  57.  */
  58. int
  59. pk_send(bp,iface,gateway,prec,del,tput,rel)
  60. struct mbuf *bp;        /* Buffer to send */
  61. struct iface *iface;    /* Pointer to interface control block */
  62. int32 gateway;            /* Ignored  */
  63. int prec;
  64. int del;
  65. int tput;
  66. int rel;
  67. {
  68.     if(iface == NULLIF){
  69.         free_p(bp);
  70.         return -1;
  71.     }
  72.     return (*iface->raw)(iface,bp);
  73. }
  74. #endif
  75.  
  76. /* Send raw packet (caller provides header) */
  77. static int
  78. pk_raw(iface,bp)
  79. struct iface *iface;    /* Pointer to interface control block */
  80. struct mbuf *bp;        /* Data field */
  81. {
  82.     register struct pktdrvr *pp;
  83.     int16 size;
  84.     struct mbuf *bp1;
  85.  
  86.     pp = &Pktdrvr[iface->dev];
  87.     size = len_p(bp);
  88.  
  89.     /* Perform class-specific processing, if any */
  90.     switch(pp->class){
  91. #ifdef ETHER
  92.     case CL_ETHERNET:
  93.         if(size < RUNT){
  94.             /* Pad the packet out to the minimum */
  95.             bp1 = ambufw(RUNT-size);
  96. /*    calloc alreday called
  97.             memset(bp1->data,0,RUNT-size);
  98. */
  99.             bp1->cnt = RUNT-size;
  100.             append(&bp,bp1);
  101.             size = RUNT;
  102.         }
  103.         break;
  104. #endif
  105.     case CL_KISS:
  106.         /* This *really* shouldn't be done here, but it was the
  107.          * easiest way. Put the type field for KISS TNC on front.
  108.          */
  109.         if((bp1 = pushdown(bp,1)) == NULLBUF){
  110.             free_p(bp);
  111.             return -1;
  112.         }
  113.         bp = bp1;
  114.         bp->data[0] = KISS_DATA;
  115.         size++;
  116.         break;
  117.     }
  118.     dump(iface,IF_TRACE_OUT,pp->class,bp);
  119.  
  120.     if(bp->next != NULLBUF){
  121.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  122.         bp1 = copy_p(bp,size);
  123.         free_p(bp);
  124.         bp = bp1;
  125.         if(bp == NULLBUF)
  126.             return -1;
  127.     }
  128.     send_pkt(pp->intno,bp->data,bp->cnt);
  129.     free_p(bp);
  130.     return 0;
  131. }
  132.  
  133. /* Packet driver receive routine. Called from an assembler hook that pushes
  134.  * the caller's registers on the stack so we can access and modify them.
  135.  * This is a rare example of call-by-location in C.
  136.  */
  137. INTERRUPT
  138. pkint(bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags, dev)
  139. unsigned short  bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags;
  140. int dev;
  141. {
  142.     register struct pktdrvr *pp;
  143.     struct phdr phdr;
  144.  
  145.     if(dev < 0 || dev >= PK_MAX)
  146.         return;    /* Unknown device */
  147.     pp = &Pktdrvr[dev];
  148.     if(pp->iface == NULLIF)
  149.         return;    /* Unknown device */
  150.     switch(ax){
  151.     case 0:    /* Space allocate call */
  152.         if((pp->buffer = alloc_mbuf(cx+sizeof(phdr))) != NULLBUF){
  153.             es = FP_SEG(pp->buffer->data);
  154.             di = FP_OFF(pp->buffer->data+sizeof(phdr));
  155.             pp->buffer->cnt = cx + sizeof(phdr);
  156.             phdr.iface = pp->iface;
  157.             phdr.type = pp->class;
  158.             memcpy(&pp->buffer->data[0],(char *)&phdr,sizeof(phdr));
  159.         } else {
  160.             es = di = 0;
  161.         }
  162.         break;
  163.     case 1:    /* Packet complete call */
  164.         enqueue(&Hopper,pp->buffer);
  165.         pp->buffer = NULLBUF;
  166.         break;
  167.     default:
  168.         break;
  169.     }
  170. }
  171.  
  172. /* Shut down the packet interface */
  173. static int
  174. pk_stop(iface,tmp)
  175. struct iface *iface;
  176. int tmp;
  177. {
  178.     struct pktdrvr *pp;
  179.  
  180.     pp = &Pktdrvr[iface->dev];
  181.     /* Call driver's release_type() entry */
  182.     if(release_type(pp->intno,pp->handle1) == -1)
  183.         tprintf("%s: release_type error code %u\n",iface->name,Derr);
  184.  
  185. #if defined(ETHER) || defined (ARCNET)
  186.     if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  187.         release_type(pp->intno,pp->handle2);
  188.         release_type(pp->intno,pp->handle3);
  189.     }
  190. #endif
  191.  
  192.     pp->iface = NULLIF;
  193.     return 0;
  194. }
  195. /* Attach a packet driver to the system
  196.  * argv[0]: hardware type, must be "packet"
  197.  * argv[1]: software interrupt vector, e.g., x7e
  198.  * argv[2]: interface label, e.g., "trw0"
  199.  * argv[3]: buffer size - not used
  200.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  201.  * argv[5]: optional ipaddr
  202.  */
  203. int
  204. pk_attach(argc,argv,p)
  205. int argc;
  206. char *argv[];
  207. void *p;
  208. {
  209.     struct iface *if_pk;
  210.     int class, type, i, xdev;
  211.     unsigned int intno;
  212.     long handle, drvvec;
  213. #ifdef ETHER
  214.     char tmp[25];
  215. #endif
  216.     char sig[8];        /* Copy of driver signature "PKT DRVR" */
  217.     struct pktdrvr *pp;
  218.  
  219. #ifdef AX25
  220.     if(*Mycall == '\0') {
  221.         tputs(Nomycall);
  222.         return -1;
  223.     }
  224. #endif
  225.     if(if_lookup(argv[2]) != NULLIF){
  226.         tprintf(Ifexist,argv[2]);
  227.         return -1;
  228.     }
  229.     for(i = 0; i < PK_MAX; i++) {
  230.         if(Pktdrvr[i].iface == NULLIF)
  231.             break;
  232.     }
  233.     if(i >= PK_MAX){
  234.         tprintf("Max %d packet drivers\n",PK_MAX);
  235.         return -1;
  236.     }
  237.  
  238.     intno = htoi(argv[1]);
  239.     /* Verify that there's really a packet driver there, so we don't
  240.      * go off into the ozone (if there's any left)
  241.      */
  242.     drvvec = (long)getvect(intno);
  243.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  244.         FP_OFF(sig),FP_SEG(sig),strlen(Pkt_sig));
  245.     if(strncmp(sig,Pkt_sig,strlen(Pkt_sig)) != 0){
  246.         tprintf("No packet driver loaded at int 0x%x\n",intno);
  247.         return -1;
  248.     }
  249.     if_pk = (struct iface *)mxallocw(sizeof(struct iface));
  250.     if_pk->name = strxdup(argv[2]);
  251.     if_pk->addr = Ip_addr;
  252.     if(argc == 4)
  253.         if((if_pk->addr = resolve(argv[5])) == 0) {
  254.             tputs(Noipaddr);
  255.             xfree(if_pk->name);
  256.             xfree((char *)if_pk);
  257.             return -1;
  258.         }
  259.     pp = &Pktdrvr[i];
  260.     if_pk->mtu = atoi(argv[4]);
  261.     if_pk->dev = i;
  262.     if_pk->xdev = 0;
  263.     if_pk->raw = pk_raw;
  264.     if_pk->stop = pk_stop;
  265.     if_pk->ioctl = pk_ioctl;        /* zba 940826 */
  266.     pp->intno = intno;
  267.     pp->iface = if_pk;
  268.  
  269.      /* Version 1.08 of the packet driver spec dropped the handle
  270.       * requirement from the driver_info call.  However, if we are using
  271.       * a version 1.05 packet driver, the following call will fail.
  272.        */
  273.      if(driver_info(intno,-1,NULL,&class,&type,NULL,NULL) < 0){
  274.         /* Find out by exhaustive search what class this driver is (ugh) */
  275.         for(class = 1; class <= NCLASS; class++) {
  276.             /* Store handle in temp long so we can tell an
  277.              * error return (-1) from a handle of 0xffff
  278.              */
  279.             handle = access_type(intno,class,ANYTYPE,0,iptype,2,
  280.                 Pkvec[if_pk->dev]);
  281.             if(handle != -1 || Derr == TYPE_INUSE){
  282.                 pp->handle1 = handle;
  283.                 break;
  284.             }
  285.         }
  286.         /* Now that we know, release it and do it all over again with the
  287.          * right type fields
  288.          */
  289.         release_type(intno,pp->handle1);
  290.     }
  291.     switch(class){
  292. #ifdef ETHER
  293.     case CL_ETHERNET:
  294.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  295.             Pkvec[if_pk->dev]);
  296.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  297.             Pkvec[if_pk->dev]);
  298.         pp->handle3 = access_type(intno,class,ANYTYPE,0,revarptype,2,
  299.             Pkvec[if_pk->dev]);
  300.         setencap(if_pk,"Ethernet");
  301.         /* Get hardware Ethernet address from driver */
  302.         if_pk->hwaddr = mxallocw(EADDR_LEN);
  303.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  304.         if(if_pk->hwaddr[0] & 1){
  305.             tprintf("Warning! Iface '%s' has a multicast address:",
  306.              if_pk->name);
  307.             tprintf(" (%s)\n",
  308.              (*if_pk->iftype->format)(tmp,if_pk->hwaddr));
  309.         }
  310.         break;
  311. #endif
  312. #ifdef    ARCNET
  313.     case CL_ARCNET:
  314.         pp->handle1 = access_type(intno,class,ANYTYPE,0,arcip,1,
  315.             Pkvec[if_pk->dev]);
  316.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arcarp,1,
  317.             Pkvec[if_pk->dev]);
  318.         if_pk->send = anet_send;
  319.         if_pk->output = anet_output;
  320.         /* Get hardware ARCnet address from driver */
  321.         if_pk->hwaddr = mxallocw(AADDR_LEN);
  322.         get_address(intno,pp->handle1,if_pk->hwaddr,AADDR_LEN);
  323.         break;
  324. #endif
  325.     case CL_SERIAL_LINE:
  326.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  327.          Pkvec[if_pk->dev]);
  328.         setencap(if_pk,"SLIP");
  329.         break;
  330. #ifdef    AX25
  331.     case CL_KISS:    /* Note that the raw routine puts on the command */
  332.     case CL_AX25:
  333.         for(xdev = 0;xdev < SLIP_MAX;xdev++){
  334.             if(Slip[xdev].iface == NULLIF)
  335.                 break;
  336.         }
  337.         if(xdev >= SLIP_MAX) {
  338.             tprintf("Max %d slip/asy/nrs devices\n",SLIP_MAX);
  339.             return -1;
  340.         }
  341.         Slip[xdev].iface = if_pk;
  342.         Slip[xdev].kiss[if_pk->port] = if_pk;        /* G1EMM */
  343.  
  344.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  345.          Pkvec[if_pk->dev]);
  346.         setencap(if_pk,"AX25");
  347.         if_pk->hwaddr = strxdup(Mycall);
  348.  
  349.         init_maxheard(if_pk);
  350.         init_flags(if_pk);
  351.         break;
  352. #endif
  353. #ifdef SLFP
  354.     case CL_SLFP:
  355.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  356.          Pkvec[if_pk->dev]);
  357.         if_pk->send = pk_send;
  358.         setencap(if_pk,"SLFP");
  359.         get_address(intno,pp->handle1,(char *)&if_pk->addr,4);
  360.         break;
  361. #endif
  362.     default:
  363.         tprintf("Packet driver has unsupported class %u\n",class);
  364.         xfree(if_pk->name);
  365.         xfree((char *)if_pk);
  366.         return -1;
  367.     }
  368.     pp->class = class;
  369.     if_pk->next = Ifaces;
  370.     Ifaces = if_pk;
  371.     if_pk->niface = Niface++;
  372.  
  373.     return 0;
  374. }
  375. static long near
  376. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  377. int intno;
  378. int if_class;
  379. int if_type;
  380. int if_number;
  381. char *type;
  382. unsigned typelen;
  383. INTERRUPT (*receiver)();
  384. {
  385.     union REGS regs;
  386.     struct SREGS sregs;
  387.  
  388.     segread(&sregs);
  389.     regs.h.dl = if_number;        /* Number */
  390.     sregs.ds = FP_SEG(type);    /* Packet type template */
  391.     regs.x.si = FP_OFF(type);
  392.     regs.x.cx = typelen;        /* Length of type */
  393.     sregs.es = FP_SEG(receiver);    /* Address of receive handler */
  394.     regs.x.di = FP_OFF(receiver);
  395.     regs.x.bx = if_type;        /* Type */
  396.     regs.h.ah = ACCESS_TYPE;    /* Access_type() function */
  397.     regs.h.al = if_class;        /* Class */
  398.     int86x(intno,®s,®s,&sregs);
  399.     if(regs.x.cflag) {
  400.         Derr = regs.h.dh;
  401.         return -1;
  402.     } else
  403.         return regs.x.ax;
  404. }
  405. static int near
  406. release_type(intno,handle)
  407. int intno;
  408. int handle;
  409. {
  410.     union REGS regs;
  411.  
  412.     regs.x.bx = handle;
  413.     regs.h.ah = RELEASE_TYPE;
  414.     int86(intno,®s,®s);
  415.     if(regs.x.cflag){
  416.         Derr = regs.h.dh;
  417.         return -1;
  418.     } else
  419.         return 0;
  420. }
  421. static int near
  422. send_pkt(intno,buffer,length)
  423. int intno;
  424. char *buffer;
  425. unsigned length;
  426. {
  427.     union REGS regs;
  428.     struct SREGS sregs;
  429.  
  430.     segread(&sregs);
  431.     sregs.ds = FP_SEG(buffer);
  432.     sregs.es = FP_SEG(buffer); /* for buggy univation pkt driver - CDY */
  433.     regs.x.si = FP_OFF(buffer);
  434.     regs.x.cx = length;
  435.     regs.h.ah = SEND_PKT;
  436.     int86x(intno,®s,®s,&sregs);
  437.     if(regs.x.cflag){
  438.         Derr = regs.h.dh;
  439.         return -1;
  440.     } else
  441.         return 0;
  442. }
  443. static int near
  444. driver_info(intno,handle,version,class,type,number,basic)
  445. int intno;
  446. int handle;
  447. int *version,*class,*type,*number,*basic;
  448. {
  449.     union REGS regs;
  450.  
  451.     regs.x.bx = handle;
  452.     regs.h.ah = DRIVER_INFO;
  453.     regs.h.al = 0xff;
  454.     int86(intno,®s,®s);
  455.     if(regs.x.cflag){
  456.         Derr = regs.h.dh;
  457.         return -1;
  458.     }
  459.     if(version != NULL)
  460.         *version = regs.x.bx;
  461.     if(class != NULL)
  462.         *class = regs.h.ch;
  463.     if(type != NULL)
  464.         *type = regs.x.dx;
  465.     if(number != NULL)
  466.         *number = regs.h.cl;
  467.     if(basic != NULL)
  468.         *basic = regs.h.al;
  469.     return 0;
  470. }
  471. static int near
  472. get_address(intno,handle,buf,len)
  473. int intno;
  474. int handle;
  475. char *buf;
  476. int len;
  477. {
  478.     union REGS regs;
  479.     struct SREGS sregs;
  480.  
  481.     segread(&sregs);
  482.     sregs.es = FP_SEG(buf);
  483.     regs.x.di = FP_OFF(buf);
  484.     regs.x.cx = len;
  485.     regs.x.bx = handle;
  486.     regs.h.ah = GET_ADDRESS;
  487.     int86x(intno,®s,®s,&sregs);
  488.     if(regs.x.cflag){
  489.         Derr = regs.h.dh;
  490.         return -1;
  491.     }
  492.     return 0;
  493. }
  494.  
  495. /*----------------------------------------------------------------------*
  496. *-----------------------------------------------------------------------*/
  497. void pkt_suspend(void)
  498. {
  499. struct pktdrvr *pp;
  500. int i;
  501.       for(i=0;i < PK_MAX;i++){         /* scan the asy structures      */
  502.          pp = &Pktdrvr[i];
  503.          if(pp->iface == NULLIF)
  504.             continue;
  505.          release_type(pp->intno,pp->handle1);
  506.          if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  507.             release_type(pp->intno,pp->handle2);
  508.             release_type(pp->intno,pp->handle3);
  509.          }
  510.       }
  511. }
  512.  
  513. /*----------------------------------------------------------------------*
  514. *-----------------------------------------------------------------------*/
  515. void pkt_restore(void)
  516. {
  517. struct pktdrvr *pp;
  518. int i;
  519.    for(i=0;i < PK_MAX;i++){
  520.       pp = &Pktdrvr[i];
  521.       if(pp->iface == NULLIF)
  522.          continue;
  523.       switch (pp->class)   {
  524. #ifdef XXX
  525.          case CL_ETHERNET:
  526.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,iptype,2, Pkvec[i]);
  527.             pp->handle2 = access_type(pp->intno,pp->class,ANYTYPE,0,arptype,2, Pkvec[i]);
  528.             pp->handle3 = access_type(pp->intno,pp->class,ANYTYPE,0,revarptype,2, Pkvec[i]);
  529.             break;
  530. #endif
  531. #ifdef  ARCNET
  532.          case CL_ARCNET:
  533.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,arcip,1, Pkvec[i]);
  534.             pp->handle2 = access_type(pp->intno,pp->class,ANYTYPE,0,arcarp,1, Pkvec[i]);
  535.             break;
  536. #endif
  537.          case CL_SERIAL_LINE:
  538.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,NULLCHAR,0, Pkvec[i]);
  539.             break;
  540. #ifdef  AX25
  541.          case CL_KISS:     /* Note that the raw routine puts on the command*/
  542.          case CL_AX25:
  543.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,NULLCHAR,0, Pkvec[i]);
  544.             break;
  545. #endif
  546. #ifdef SLFP
  547.          case CL_SLFP:
  548.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,NULLCHAR,0, Pkvec[i]);
  549.             break;
  550. #endif
  551.       }
  552.    }
  553. }
  554.  
  555. /* ------------------------------------------------------------------------- */
  556. /*  This function will provide ioctl for a packet driver interface.
  557.  *  It will only work together with a modified version of the ax25-driver.
  558.  *  Only param. #5 (fullduplex on/off) can be changed via this function.
  559.  *  dl6zba 940826
  560.  */
  561. static int
  562. pk_ioctl(iface, argc, argv)
  563. struct iface *iface;
  564. int argc;
  565. char *argv[];
  566. {
  567.     union REGS regs;
  568.     struct pktdrvr *pp;
  569.  
  570.     if ( *argv[0] == '5' ) {
  571.         pp = &Pktdrvr[iface->dev];
  572.         regs.x.cx = (*argv[1] == '0') ? 0 : 1;
  573.         regs.h.ah = AX25_FULLDUPLEX;
  574.         int86(pp->intno, ®s, ®s);
  575.     } else
  576.         return -1;      /* not supported */
  577.     return (regs.x.cflag) ? -1 : 0;
  578. }
  579. /* ------------------------------------------------------------------------- */
  580.  
  581. #endif PACKET
  582.  
  583.  
  584.